package connect_mgr

import (
	"common/connect_mgr/list_set"
	"common/uuid"
	"context"
	"fmt"
	"time"
)

const MaxDeviceCount = 20

var updateHandle UpdateHandle
var set *list_set.Set[Device]
var DebugDeviceId string
var needNodesChan chan int

type Device struct {
	Id     string
	Port   uint16
	NodeId uuid.UUID
}

func init() {
	set = list_set.NewSet[Device](func(a, b Device) bool {
		return a.Id == b.Id
	})
	needNodesChan = make(chan int)
}

type UpdateHandle interface {
	UpdateNode(ctx context.Context, update int32, include [][]byte, exclude [][]byte) []Device
	GetNodeByDevice(ctx context.Context, deviceId string) (*Device, error)
}

func SetUpdateHandle(u UpdateHandle) {
	updateHandle = u
}

func SetDebugDevice(u string) {
	DebugDeviceId = u
}

func GetExistDeviceNodeId() [][]byte {
	nodeids := make([][]byte, 0)
	existDevice := set.ToSlice()
	for i := range existDevice {
		nodeids = append(nodeids, existDevice[i].NodeId.Bytes())
	}
	return nodeids
}
func updateNodes(ctx context.Context, updateCount int32) {
	if updateHandle != nil {
		if len(DebugDeviceId) > 0 { //debug 模式
			fmt.Println("调试单个节点模式,设备", DebugDeviceId)
			node, err := updateHandle.GetNodeByDevice(ctx, DebugDeviceId)
			if err != nil {
				fmt.Println("GetNodeByDevice err", err)
			}
			output := []Device{*node}
			fleshDevice := set.Diff(output...)
			push(fleshDevice)
		} else {
			existNodes := GetExistDeviceNodeId()
			output := updateHandle.UpdateNode(ctx, updateCount, nil, existNodes)
			fleshDevice := set.Diff(output...)
			fmt.Println("更新节点", len(output), "实际更新", len(fleshDevice))
			push(fleshDevice)
		}
	}
}
func StartConnectServer(ctx context.Context) {
	updateTimer := time.NewTicker(time.Second * 1)
	var updateCount int32 = 7
	for {
		select {
		case needCount := <-needNodesChan:
			fmt.Println("need count", needCount)
			updateNodes(ctx, int32(needCount))
		case <-updateTimer.C:
			updateNodes(ctx, updateCount)
			updateTimer.Reset(time.Second * 30)
			updateCount = 3
		case <-ctx.Done():
			return
		}
	}
}
func PushAsync(inputs []Device) {
	fleshDevice := set.Diff(inputs...)
	fmt.Println("更新节点", len(inputs), "实际更新", len(fleshDevice))
	go push(fleshDevice)
}

func push(inputs []Device) {
	for _, input := range inputs {
		var remotePort uint16 = input.Port
		key := input.Id
		fmt.Println("input.Id", input.Id)
		addConnect(key, input.Id, input.NodeId, remotePort, 20000, false)
		set.PushN(input)
	}
	var removeCount = set.Size() - MaxDeviceCount
	if removeCount > 0 {
		removeDevice := set.PopN(removeCount)
		for _, d := range removeDevice {
			delConnect(d.Id)
			fmt.Println("delConnect", d.Id)

		}
	}
}
